package com.cloud.rou.im.client.statemachine;

import lombok.AllArgsConstructor;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;

/**
 * <p></p>
 *
 * @author GaoShuangWen
 */
@AllArgsConstructor
public class StateAction {

    private MsgState state;

    private MsgListener<StateMachineContext> entry;

    private MsgListener<StateMachineContext> exit;

    private Map<MsgEvent, Transition> transitions = new HashMap<>();

    private Predicate<StateMachineContext> condition = StateMachineContext::getFlag;

    public MsgState getState() {
        return state;
    }

    public void entry(StateMachineContext context) {
        if (null != entry) {
            entry.listen(context);
        }
    }

    public void exit(StateMachineContext context) {
        if (null != exit) {
            exit.listen(context);
        }
    }

    public Transition getTransition(MsgEvent event) {
        return transitions.get(event);
    }

    public static Builder builder(MsgState state) {
        return new Builder(state);
    }

    public static class Builder {
        // 状态
        private MsgState state;
        private Predicate<StateMachineContext> condition;
        private MsgListener<StateMachineContext> entry;
        private MsgListener<StateMachineContext> exit;
        private Map<MsgEvent, Transition.Builder> maps = new HashMap<>();
        private Map<MsgEvent, Transition> transitions = new HashMap<>();

        public Builder(MsgState state) {
            this.state = state;
        }

        public Transition.Builder event(MsgEvent event) {
            Transition.Builder builder = this.maps.get(event);
            if (builder != null) {
                return builder;
            }
            Transition.Builder builder1 = Transition.builder();
            maps.put(event,builder1);
            return builder1;
        }

        public Builder entry(MsgListener<StateMachineContext> entry) {
            this.entry = entry;
            return this;
        }
        public Builder condition(Predicate<StateMachineContext> condition) {
            this.condition = condition;
            return this;
        }

        public Builder exit(MsgListener<StateMachineContext> exit) {
            this.exit = exit;
            return this;
        }

        public StateAction build() {
            this.maps.forEach((state, builder) -> {
                Transition transition = builder.build();
                this.transitions.put(state, transition);
            });
            return new StateAction(state, entry, exit, transitions, StateMachineContext::getFlag);
        }
    }
}
